
#include "render_menu.h"


RenderMenu::RenderMenu()
{

}

RenderMenu::~RenderMenu()
{

}

void		RenderMenu::init()
{
  this->buttonSelected = MENU_NO_BUTTON_SELECT;
  this->selectLevel = MENU_SEL_LEVEL_PRIMARY;
  this->clickPicking = MENU_NO_CLICK_TEST;
}

void		RenderMenu::normalKeyEvent(unsigned char key, int x, int y)
{
  switch(key)
    {
    case 27: // echap
      exit(EXIT_SUCCESS);
      break;
    case 113: // q
      exit(EXIT_SUCCESS);
      break;
    default:
      std::cout << "unknow key press : " << (int)key << std::endl;
      break;
    }
  glutPostRedisplay();
}

void		RenderMenu::setupRc()
{
  float		Width = 1280.0f;
  float		Height = 1024.0f;

  LoadGLTextures();				// Load The Texture(s)
  glEnable(GL_TEXTURE_2D);			// Enable Texture Mapping

 //  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//   glEnable(GL_BLEND);
  // for points
  glEnable(GL_POINT_SMOOTH);
  glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
  // for lines
  glEnable(GL_LINE_SMOOTH);
  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  // for polygons
  glEnable(GL_POLYGON_SMOOTH);
  glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);

  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	// Clear The Background Color To Blue
  glClearDepth(1.0);				// Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);			// The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);			// Enables Depth Testing
  glShadeModel(GL_SMOOTH);			// Enables Smooth Color Shading

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();				// Reset The Projection Matrix

  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);	// Calculate The Aspect Ratio Of The Window

  glMatrixMode(GL_MODELVIEW);
  glDepthFunc(GL_LESS);

  // blending
  glColor4f(1.0f,1.0f,1.0f,0.5f);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE);

}

void		RenderMenu::LoadGLTextures()
{
  // Load Texture
  Image *image1;

  // allocate space for texture
  image1 = (Image *) malloc(sizeof(Image));
  if (image1 == NULL) {
    printf("Error allocating space for image");
    exit(0);
  }

  if (!ImageLoad(MENU_BACKGROUND_PIC_PATH, image1)) {
    exit(1);
  }

  // Create Texture
  glGenTextures(1, &texture[0]);
  glBindTexture(GL_TEXTURE_2D, texture[0]);   // 2d texture (x and y size)

  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture

  // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
  // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
  glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
}

int		RenderMenu::ImageLoad(char *filename, Image *image)
{
  FILE *file;
  unsigned long size;                 // size of the image in bytes.
  unsigned long i;                    // standard counter.
  unsigned short int planes;          // number of planes in image (must be 1)
  unsigned short int bpp;             // number of bits per pixel (must be 24)
  char temp;                          // temporary color storage for bgr-rgb conversion.

  // make sure the file is there.
  if ((file = fopen(filename, "rb"))==NULL)
    {
      printf("File Not Found : %s\n",filename);
      return 0;
    }

  // seek through the bmp header, up to the width/height:
  fseek(file, 18, SEEK_CUR);

  // read the width
  if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
    printf("Error reading width from %s.\n", filename);
    return 0;
  }
  printf("Width of %s: %lu\n", filename, image->sizeX);

  // read the height
  if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
    printf("Error reading height from %s.\n", filename);
    return 0;
  }
  printf("Height of %s: %lu\n", filename, image->sizeY);

  // calculate the size (assuming 24 bits or 3 bytes per pixel).
  size = image->sizeX * image->sizeY * 3;

  // read the planes
  if ((fread(&planes, 2, 1, file)) != 1) {
    printf("Error reading planes from %s.\n", filename);
    return 0;
  }
  if (planes != 1) {
    printf("Planes from %s is not 1: %u\n", filename, planes);
    return 0;
  }

  // read the bpp
  if ((i = fread(&bpp, 2, 1, file)) != 1) {
    printf("Error reading bpp from %s.\n", filename);
    return 0;
  }
  if (bpp != 24) {
    printf("Bpp from %s is not 24: %u\n", filename, bpp);
    return 0;
  }

  // seek past the rest of the bitmap header.
  fseek(file, 24, SEEK_CUR);

  // read the data.
  image->data = (char *) malloc(size);
  if (image->data == NULL) {
    printf("Error allocating memory for color-corrected image data");
    return 0;
  }

  if ((i = fread(image->data, size, 1, file)) != 1) {
    printf("Error reading image data from %s.\n", filename);
    return 0;
  }

  for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
    temp = image->data[i];
    image->data[i] = image->data[i+2];
    image->data[i+2] = temp;
  }

  // we're done.
  return 1;
}

void		RenderMenu::render()
{
  int		objHit;

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  if(this->pickingMode == PICKING_MODE_ON)
    this->startPicking(this->xToPick, this->yToPick);

  glShadeModel(GL_SMOOTH);
  glTranslatef(0.0f,0.0f,-5.0f);

  glColor3f(1.0f, 1.0f, 1.0f);
  glBindTexture(GL_TEXTURE_2D, this->texture[0]);

  glInitNames();
  glPushName(0);
  glLoadName(999);

  glBegin(GL_QUADS);
  glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-2.4f, -2.0f, 1.0f);
  glTexCoord2f(1.0f, 0.0f);
  glVertex3f( 2.4f, -2.0f, 1.0f);
  glTexCoord2f(1.0f, 1.0f);
  glVertex3f( 2.4f,  2.0f, 1.0f);
  glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-2.4f,  2.0f, 1.0f);
  glEnd();

  // dirty removal of texture stack ... need to change that!!!
  glBindTexture(GL_TEXTURE_2D, (GLuint)NULL);

  this->showButtons(this->buttonSelected);

  if(this->boxToDisplay != 0)
    {
      std::cout << "display boxL:" << this->boxToDisplay << std::endl;
      this->showMenuBox();
    }

  if(pickingMode == PICKING_MODE_ON)
    {
      std::cout << "pick level:" << this->selectLevel << std::endl;
      if((objHit = this->stopPicking(this->selectLevel)) > 0)
	this->buttonSelected = objHit;
      if(clickPicking != MENU_NO_CLICK_TEST
	 && this->boxToDisplay == MENU_BOX_TO_DISPLAY_NONE)
	this->getBoxToDisplay(objHit);
    }
  else
    glutSwapBuffers(); // flush drawing cmd
}

void		RenderMenu::showMenuBox()
{
  switch(this->boxToDisplay)
    {
    case MENU_BOX_TO_DISPLAY_EXIT:
      this->drawSquareCCW(-0.5f, 0.5f, 1.0f, 1.0f, 2.0f
			       , 0.0f, 1.0f, 0.0f, 0.5f, 66);
      break;
    default:
      this->boxToDisplay = MENU_BOX_TO_DISPLAY_NONE;
      break;
    }
}

void		RenderMenu::getBoxToDisplay(int	objHit)
{
  switch(objHit)
    {
    case MENU_BOX_TO_DISPLAY_START:
      break;
    case MENU_BOX_TO_DISPLAY_LOAD:
      break;
    case MENU_BOX_TO_DISPLAY_SAVE:
      break;
    case MENU_BOX_TO_DISPLAY_EXIT:
      this->boxToDisplay = objHit;
      this->selectLevel = MENU_SEL_LEVEL_BOX;
      break;
    default:
      this->boxToDisplay = MENU_BOX_TO_DISPLAY_NONE;
      this->selectLevel = MENU_SEL_LEVEL_PRIMARY;
      break;
    }
}

void		RenderMenu::showButtons(int buttonSelected)
{
  bool		select = false;

  if(buttonSelected == 2)
    select = true;
  this->printButton(MENU_START_LABEL, 2, select);

  select = false;
  if(buttonSelected == 3)
    select = true;
  this->printButton(MENU_LOAD_LABEL, 3, select);


  select = false;
  if(buttonSelected == 4)
    select = true;
  this->printButton(MENU_SAVE_LABEL, 4, select);

  select = false;
  if(buttonSelected == 5)
    select = true;
  this->printButton(MENU_EXIT_LABEL, 5, select);

}

void		RenderMenu::printButton(char *label, int pos, bool selected)
{
  float		spaceH;
  int		wrapXword;
  float		wrapYword;
  float		win;


  spaceH = ((pos - 1) * 0.2f);

  // start transparancy
  glEnable(GL_BLEND);
  glDisable(GL_DEPTH_TEST);

  if(selected == true)
    glColor4f(0.1f, 0.1f, 0.1f, 0.9f);
  else
    glColor3f(0.15f, 0.15f, 0.15f);


  glLoadName(pos);
  glBegin(GL_QUADS);
  glVertex3f(-0.4f , -0.07f - spaceH,  1.1f);
  glVertex3f(0.4f, -0.07f - spaceH,  1.1f);
  glVertex3f(0.4f, 0.07f - spaceH,  1.1f);
  glVertex3f(-0.4f,  0.07f - spaceH,  1.1f);
  glEnd();

  glDisable(GL_BLEND);
  glEnable(GL_DEPTH_TEST);

  win = (float)this->windowH;
  wrapYword = MENU_RATIO - spaceH;
  wrapYword = ((win / (MENU_RATIO)) * wrapYword) / 2.0f;
  wrapXword = ((this->windowW / 2) - ((strlen(label) * 5) / 2));

  if(selected == true)
    printText(wrapXword, (int)wrapYword
	      , label, 1.0f, 1.0f, 1.0f);
  else
    printText(wrapXword, (int)wrapYword
	      , label, 0.0f, 0.0f, 0.0f);

}

void		RenderMenu::mousePassiveMotion(int x, int y)
{
  this->pickingMode = PICKING_MODE_ON;
  this->xToPick = x;
  this->yToPick = y;

  this->render();
  this->render();
  this->buttonSelected = MENU_NO_BUTTON_SELECT;
}

void		RenderMenu::mouseEvent(int button, int state, int x, int y)
{
  if(state == 0 && button == 0)
    {
      this->pickingMode = PICKING_MODE_ON;
      this->xToPick = x;
      this->yToPick = y;

      this->clickPicking = 1;
      this->render();
      this->render();
      this->clickPicking = MENU_NO_CLICK_TEST;
    }

}

void		RenderMenu::changeSize(GLsizei w, GLsizei h)
{
  if (h == 0)				// Prevent A Divide By Zero If The Window Is Too Small
    h = 1;
  this->windowH = (int)h;
  this->windowW = (int)w;

  glViewport(0, 0, w, h);		// Reset The Current Viewport And Perspective Transformation

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  gluPerspective(45.0f,(GLfloat)w/(GLfloat)h,0.1f,100.0f);
  glMatrixMode(GL_MODELVIEW);

}

